<script setup name="Role" lang="ts">
import {
  MenuOutlined,
} from '@ant-design/icons-vue'
import { TreeSelect } from 'ant-design-vue'
import { parseTime } from '../../../utils/ruoyi.ts'
import auth from './auth.vue'
import {
  addRole,
  changeRoleStatus,
  dataScope,
  delRole,
  deptTreeSelect,
  getRole,
  listRole,
  updateRole,
} from '@/api/system/role'
import { treeselect as menuTreeselect, roleMenuTreeselect } from '@/api/system/menu/index'
import type { DeptTreeOption, RoleForm, RoleQuery, RoleVO } from '@/api/system/role/types'
import type { MenuTreeOption, RoleMenuTree } from '@/api/system/menu/types'
import type { UserVO } from '~/api/system/user/types.ts'

const message = useMessage()
const modal = useModal()
const roleList = ref<RoleVO[]>()
const loading = ref(true)
const ids = ref<Array<string | number>>([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const menuOptions = ref<MenuTreeOption[]>([])
const menuExpand = ref(false)
const menuNodeAll = ref(false)
const deptExpand = ref(true)
const deptNodeAll = ref(false)
const deptOptions = ref<DeptTreeOption[]>([])
const openDataScope = ref(false)
const openAuthModal = ref(false)
const authRuleId = ref()
const authRuleRef = ref()

/** 数据范围选项 */
const dataScopeOptions = ref([
  { value: '1', label: '全部数据权限' },
  { value: '2', label: '自定数据权限' },
  { value: '3', label: '本部门数据权限' },
  { value: '4', label: '本部门及以下数据权限' },
  { value: '5', label: '仅本人数据权限' },
])

const roleFormRef = ref()
const dataScopeRef = ref()
const deptRef = ref()

const SHOW_PARENT = TreeSelect.SHOW_ALL

const initForm: RoleForm = {
  roleId: undefined,
  roleSort: 1,
  status: '0',
  roleName: '',
  roleKey: 'admin_',
  menuCheckStrictly: true,
  deptCheckStrictly: true,
  remark: '',
  dataScope: '1',
  menuIds: [],
  deptIds: [],
}

const data = reactive<PageData<RoleForm, RoleQuery>>({
  form: { ...initForm },
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    roleName: '',
    roleKey: '',
    status: '',
  },
  rules: {
    roleName: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
    roleKey: [{ required: true, message: '权限字符不能为空', trigger: 'blur' }],
    roleSort: [{ required: true, message: '角色顺序不能为空', trigger: 'blur' }],
  },
})
const { form, queryParams, rules } = toRefs(data)

const dialog = reactive<DialogOption>({
  visible: false,
  title: '',
})

/**
 * 查询角色列表
 */
function getList() {
  loading.value = true
  listRole(queryParams.value).then((res) => {
    roleList.value = res.rows
    total.value = res.total
    loading.value = false
  })
}

/**
 * 搜索按钮操作
 */
function handleQuery() {
  queryParams.value.pageNum = 1
  getList()
}

/** 删除按钮操作 */
async function handleDelete(row?: RoleVO) {
  const roleids = row?.roleId || ids.value
  modal.confirm({
    title: `确认删除角色[${row?.roleName}]?`,
    onOk: async () => {
      await delRole(roleids)
      getList()
      message.success('删除成功')
    },
  })
}

/** 多选框选中数据 */
function handleSelectionChange(selection: RoleVO[]) {
  ids.value = selection.map((item: RoleVO) => item.roleId)
  single.value = selection.length !== 1
  multiple.value = !selection.length
}

/** 角色状态修改 */
async function handleStatusChange(row: RoleVO) {
  const text = row.status === '0' ? '启用' : '停用'
  try {
    modal.confirm({
      title: `确认要${text}[${row.roleName}]角色吗?`,
      onOk: async () => {
        await changeRoleStatus(row.roleId, row.status)
        getList()
        message.success(`${text}成功`)
      },
      onCancel: () => {
        row.status = row.status === '0' ? '1' : '0'
      },
    })
  }
  catch {
    row.status = row.status === '0' ? '1' : '0'
  }
}

/** 分配用户 */
function handleAuthUser(roleId: string | number) {
  authRuleId.value = roleId
  openAuthModal.value = true
}

/** 查询菜单树结构 */
async function getMenuTreeselect() {
  const res = await menuTreeselect()
  menuOptions.value = res.data
}

/** 重置新增的表单以及其他数据  */
function reset() {
  menuExpand.value = false
  menuNodeAll.value = false
  deptExpand.value = true
  deptNodeAll.value = false
  form.value = { ...initForm }
  roleFormRef.value?.resetFields()
}

/** 添加角色 */
function handleAdd() {
  reset()
  getMenuTreeselect()
  dialog.visible = true
  dialog.title = '新增角色'
}

/** 修改角色 */
async function handleUpdate(row?: RoleVO) {
  reset()
  const roleId = row?.roleId || ids.value[0]
  const { data } = await getRole(roleId)
  Object.assign(form.value, data)
  form.value.roleSort = Number(form.value.roleSort)
  const res = await getRoleMenuTreeselect(roleId)
  dialog.title = '修改角色'
  dialog.visible = true
  form.value.menuIds = res.checkedKeys
}

/** 根据角色ID查询菜单树结构 */
function getRoleMenuTreeselect(roleId: string | number) {
  return roleMenuTreeselect(roleId).then((res): RoleMenuTree => {
    menuOptions.value = res.data.menus
    return res.data
  })
}

/** 根据角色ID查询部门树结构 */
async function getRoleDeptTreeSelect(roleId: string | number) {
  const res = await deptTreeSelect(roleId)
  deptOptions.value = res.data.depts
  return res.data
}
/** 提交按钮 */
function submitForm(type: number) {
  roleFormRef.value?.validate().then(async () => {
    if (form.value.roleId) {
      await updateRole(form.value)
      message.success('修改成功')
    }
    else {
      const res = await addRole(form.value)
      message.success('新增成功')
      if (type === 1)
        handleAuthUser(res.data)
    }

    dialog.visible = false
    getList()
  })
}

/** 取消按钮 */
function cancel() {
  reset()
  dialog.visible = false
}

/** 选择角色权限范围触发 */
function dataScopeSelectChange(value: any) {
  if (value !== '2')
    deptRef.value?.setCheckedKeys([])
}

/** 分配数据权限操作 */
async function handleDataScope(row: RoleVO) {
  const response = await getRole(row.roleId)
  Object.assign(form.value, response.data)
  const res = await getRoleDeptTreeSelect(row.roleId)
  openDataScope.value = true
  dialog.title = '分配数据权限'
  form.value.deptIds = res.checkedKeys
}

/** 提交按钮（数据权限） */
async function submitDataScope() {
  if (form.value.roleId) {
    await dataScope(form.value)
    message.success('修改成功')
    openDataScope.value = false
    getList()
  }
}

/** 提交按钮（数据权限） */
async function submitAuthModal() {
  await authRuleRef.value.submit()
  message.success('授权成功')
  openAuthModal.value = false
  getList()
}

/** 取消按钮（数据权限） */
function cancelDataScope() {
  dataScopeRef.value?.resetFields()
  form.value = { ...initForm }
  openDataScope.value = false
}

// 已取消和已结算的
function rowClassName(record: UserVO) {
  if (record.status === '1')
    return 'depart-row-class'
}

onMounted(() => {
  getList()
})
</script>

<template>
  <div>
    <a-card class="mb-20px">
      <bh-table-title v-model:value="queryParams.roleName" :show-filtering="false" placeholder="输入角色名称，按回车键搜索" @show-modal="handleAdd" @on-query="handleQuery" />
    </a-card>
    <a-card>
      <a-table :loading="loading" :row-class-name="rowClassName" :pagination="false" :data-source="roleList" @selection-change="handleSelectionChange">
        <a-table-column title="角色名称" :width="160" data-index="roleName" :ellipsis="true" />
        <a-table-column title="角色配置人数" :width="120" data-index="number" :ellipsis="true" />
        <a-table-column title="创建时间" align="left" data-index="createTime" :width="160">
          <template #default="{ record }">
            <span>{{ parseTime(record.createTime) }}</span>
          </template>
        </a-table-column>
        <a-table-column title="描述" data-index="remark" :ellipsis="true" :width="200" />
        <a-table-column fixed="right" title="操作" :width="280">
          <template #default="{ record }">
            <a-space v-if="record.roleId !== 1" :size="20">
              <a-button
                v-hasPermi="['system:role:edit']"
                type="link"
                @click="handleAuthUser(record.roleId)"
              >
                <span>授权</span>
              </a-button>

              <a-button
                v-hasPermi="['system:role:edit']"
                class="op-span" type="link"
                @click="handleUpdate(record)"
              >
                <span>编辑</span>
              </a-button>
              <a-button
                v-hasPermi="['system:role:remove']"
                class="op-span" type="link"
                @click="handleDelete(record)"
              >
                <span>删除</span>
              </a-button>

              <span class="op-span">
                <a-switch v-model:checked="record.status" checked-value="0" un-checked-value="1" @change="handleStatusChange(record)" />
              </span>
              <a-tooltip content="数据权限" placement="top">
                <a-button
                  v-hasPermi="['system:role:edit']" type="link"
                  @click="handleDataScope(record)"
                >
                  <MenuOutlined />
                </a-button>
              </a-tooltip>
            </a-space>
          </template>
        </a-table-column>
      </a-table>

      <div class="text-right mt-20px">
        <a-pagination
          v-show="total > 0"
          v-model:current="queryParams.pageNum" v-model:pageSize="queryParams.pageSize" :total="total"
          show-less-items @change="getList"
        />
      </div>

      <a-modal v-model:open="dialog.visible" :mask-closable="false" :keyboard="false" destroy-on-close :title="dialog.title" width="500px" append-to-body>
        <div class="mt-20px">
          <a-form ref="roleFormRef" :hide-required-mark="true" :model="form" class="block-form" :rules="rules" layout="vertical" :label-col="{ style: 'width:100px' }">
            <a-form-item label="角色名称" name="roleName" class="required">
              <a-input v-model:value="form.roleName" placeholder="请输入角色名称" />
            </a-form-item>
            <a-form-item label="备注">
              <a-textarea v-model:value="form.remark" placeholder="请输入内容" />
            </a-form-item>
          </a-form>
        </div>
        <template #footer>
          <div class="dialog-footer">
            <a-button @click="cancel">
              取 消
            </a-button>

            <a-button type="primary" @click="submitForm(0)">
              保存
            </a-button>
          </div>
        </template>
      </a-modal>

      <!-- 分配角色数据权限对话框 -->
      <a-modal v-model:open="openDataScope" :mask-closable="false" :keyboard="false" :title="dialog.title" width="500px" append-to-body>
        <a-form ref="dataScopeRef" :model="form" :label-col="{ style: 'width:80px' }">
          <a-form-item title="角色名称">
            <a-input v-model:value="form.roleName" :disabled="true" />
          </a-form-item>
          <a-form-item title="权限字符">
            <a-input v-model:value="form.roleKey" :disabled="true" />
          </a-form-item>
          <a-form-item label="权限范围">
            <a-select v-model:value="form.dataScope" @change="dataScopeSelectChange">
              <a-select-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label" :value="item.value">
                {{ item.label }}
              </a-select-option>
            </a-select>
          </a-form-item>
          <a-form-item v-show="form.dataScope === '2'" label="数据权限">
            <a-tree-select
              ref="deptRef"
              v-model:value="form.deptIds"
              class="tree-border"
              :tree-data="deptOptions"
              tree-checkable
              allow-clear
              :tree-default-expand-all="true"
              :show-checked-strategy="SHOW_PARENT"
              tree-node-filter-prop="label"
              :field-names="{ label: 'label', value: 'id', children: 'children' }"
            />
          </a-form-item>
        </a-form>
        <template #footer>
          <div class="dialog-footer">
            <a-button type="primary" @click="submitDataScope">
              确 定
            </a-button>
            <a-button @click="cancelDataScope">
              取 消
            </a-button>
          </div>
        </template>
      </a-modal>

      <!-- 分配角色数据权限对话框 -->
      <a-modal v-model:open="openAuthModal" :mask-closable="false" :keyboard="false" destroy-on-close title="授权" width="800px">
        <auth ref="authRuleRef" :role-id="authRuleId" />
        <template #footer>
          <div class="dialog-footer">
            <a-button @click="openAuthModal = false">
              取 消
            </a-button>

            <a-button type="primary" @click="submitAuthModal">
              保 存
            </a-button>
          </div>
        </template>
      </a-modal>
    </a-card>
  </div>
</template>

<style scoped lang="less">
@import "@/components/bh-table/index.less";
:deep(.ant-table-empty){
  .ant-table-cell{
    background: #f0f2f5;
  }
  .ant-table-placeholder:hover > td{
    background: #f0f2f5 !important;
  }
}
</style>
